package org.example.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.extern.slf4j.Slf4j;
import org.example.mapper.ScoreMapper;
import org.example.model.Dto.Student;
import org.example.model.Dto.TeacherDto;
import org.example.model.table.ClassTable;
import org.example.model.table.Course;
import org.example.model.table.Score;
import org.example.model.table.User;
import org.example.model.vo.ScoreVo;
import org.example.service.ScoreService;
import org.example.util.CommonUtil;
import org.example.util.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Slf4j
@Service
public class ScoreServiceImpl implements ScoreService {
    @Autowired
    ScoreMapper scoreMapper;

    @Override
    public Result getAllScore(int page, int size) {
        IPage<ScoreVo> scoreVoIPage = scoreMapper.selectJoinPage(new Page<ScoreVo>(page, size), ScoreVo.class,
                new MPJLambdaWrapper<Score>()
                        .selectAs(Course::getName, ScoreVo::getCourseName)
                        .innerJoin(Course.class, Course::getId, Score::getCourseId)
                        .selectAs(Score::getId, ScoreVo::getId)
                        .selectAs(Score::getMark, ScoreVo::getMark)
                        .selectAs(ClassTable::getName, ScoreVo::getClassName)
                        .innerJoin(ClassTable.class, ClassTable::getId, Course::getId)
                        .selectAs(TeacherDto::getName, ScoreVo::getTeacherName)
                        .innerJoin(TeacherDto.class, TeacherDto::getId, Course::getTeacherId)
                        .selectAs(Student::getName, ScoreVo::getStudentName)
                        .innerJoin(Student.class, Student::getId, Score::getStudentId)
        );

        if (scoreVoIPage != null && scoreVoIPage.getRecords().size() > 0) {


            return Result.ok().data("scoreInfo", scoreVoIPage);
        }

        return Result.ok().data("msg", "暂无数据").setCode(404);
    }

    @Override
    public Result getAllScoreByUserId(int page, int size, Long id) {
        IPage<ScoreVo> scoreVoIPage = scoreMapper.selectJoinPage(new Page<ScoreVo>(page, size), ScoreVo.class,
                new MPJLambdaWrapper<Score>()
                        .selectAs(Course::getName, ScoreVo::getCourseName)
                        .innerJoin(Course.class, Course::getId, Score::getCourseId)
                        .selectAs(Score::getId, ScoreVo::getId)
                        .selectAs(Score::getMark, ScoreVo::getMark)
                        .selectAs(ClassTable::getName, ScoreVo::getClassName)
                        .innerJoin(ClassTable.class, ClassTable::getId, Course::getId)
                        .selectAs(TeacherDto::getName, ScoreVo::getTeacherName)
                        .innerJoin(TeacherDto.class, TeacherDto::getId, Course::getTeacherId)
                        .selectAs(Student::getName, ScoreVo::getStudentName)
                        .innerJoin(Student.class, Student::getId, Score::getStudentId)
                        .eq(Student::getId, id)
        );
        if (scoreVoIPage != null && scoreVoIPage.getRecords().size() > 0)
            return Result.ok().data("scoreInfo", scoreVoIPage);
        return Result.ok().data("msg", "暂无数据").setCode(404);
    }

    @Override
    public Result getAllScoreByClassId(int page, int size, Long id) {
        IPage<ScoreVo> scoreVoIPage = scoreMapper.selectJoinPage(new Page<ScoreVo>(page, size), ScoreVo.class,
                new MPJLambdaWrapper<Score>()
                        .selectAs(Course::getName, ScoreVo::getCourseName)
                        .innerJoin(Course.class, Course::getId, Score::getCourseId)
                        .selectAs(Score::getId, ScoreVo::getId)
                        .selectAs(Score::getMark, ScoreVo::getMark)
                        .selectAs(ClassTable::getName, ScoreVo::getClassName)
                        .innerJoin(ClassTable.class, ClassTable::getId, Course::getId)
                        .selectAs(TeacherDto::getName, ScoreVo::getTeacherName)
                        .innerJoin(TeacherDto.class, TeacherDto::getId, Course::getTeacherId)
                        .selectAs(Student::getName, ScoreVo::getStudentName)
                        .innerJoin(Student.class, Student::getId, Score::getStudentId)
                        .eq(ClassTable::getId, id)
        );
        if (scoreVoIPage != null && scoreVoIPage.getRecords().size() > 0)
            return Result.ok().data("scoreInfo", scoreVoIPage);
        return Result.ok().data("msg", "暂无数据").setCode(404);
    }

    @Override
    public Result getAllScoreByTeacherId(int page, int size, Long id) {
        IPage<ScoreVo> scoreVoIPage = scoreMapper.selectJoinPage(new Page<ScoreVo>(page, size), ScoreVo.class,
                new MPJLambdaWrapper<Score>()
                        .selectAs(Course::getName, ScoreVo::getCourseName)
                        .innerJoin(Course.class, Course::getId, Score::getCourseId)
                        .selectAs(Score::getId, ScoreVo::getId)
                        .selectAs(Score::getMark, ScoreVo::getMark)
                        .selectAs(ClassTable::getName, ScoreVo::getClassName)
                        .innerJoin(ClassTable.class, ClassTable::getId, Course::getId)
                        .selectAs(TeacherDto::getName, ScoreVo::getTeacherName)
                        .innerJoin(TeacherDto.class, TeacherDto::getId, Course::getTeacherId)
                        .selectAs(Student::getName, ScoreVo::getStudentName)
                        .innerJoin(Student.class, Student::getId, Score::getStudentId)
                        .eq(TeacherDto::getId, id)
        );
        if (scoreVoIPage != null && scoreVoIPage.getRecords().size() > 0)
            return Result.ok().data("scoreInfo", scoreVoIPage);
        return Result.ok().data("msg", "暂无数据").setCode(404);
    }

    @Override
    public Result deleteScoreById(Long id) {
        int i = scoreMapper.deleteById(id);
        return i == 1 ?
                Result.ok().data("msg", "成功删除") :
                Result.error().data("msg", "删除失败").setCode(501);
    }

    @Override
    public Result deleteScoreByIds(List<Long> ids) {
        Map<Long, String> map = new HashMap<>();
        Result ok = Result.ok();
        for (Long id : ids) {
            try {
                int i = scoreMapper.deleteById(id);
                if (i == 1)
                    map.put(id, "成功");
                else map.put(id, "失败");
            } catch (Exception e) {
                map.put(id, "失败");
                ok.data("error", e.getMessage());
            }

        }
        return ok.data("lists", map);
    }

    @Override
    public Result changeScore(Score score) {
        int i = scoreMapper.updateById(score);
        return i == 1 ?
                Result.ok().data("msg", "成功更改") :
                Result.error().data("msg", "更改失败").setCode(501);
    }

    @Override
    public Result addScore(Score score) {
        LambdaQueryWrapper<Score> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Score::getStudentId, score.getStudentId())
                .eq(Score::getCourseId, score.getCourseId());
        if (scoreMapper.selectOne(wrapper) == null) {
            int insert = scoreMapper.insert(score);
            return insert == 1 ?
                    Result.ok().data("msg", "成功插入") :
                    Result.error().data("msg", "插入失败").setCode(501);
        } else {
            return Result.error().data("msg", "插入失败， 数据已存在").setCode(501);
        }
    }

    @Override
    public Result getScorePage(Integer page, Integer size, ScoreVo scoreVo) {
        int lower = 0;
        int upper = 100;
        if (scoreVo.getMark() != null) {
            int[] range = CommonUtil.findRange(scoreVo.getMark());
            lower = range[0];
            upper = range[1];
        }
        MPJLambdaWrapper<Score> wrapper = new MPJLambdaWrapper<>();
        wrapper
                .selectAs(Score::getId, ScoreVo::getId)
                .selectAs(User::getId, ScoreVo::getStudentId)
                .selectAs(User::getName, ScoreVo::getStudentName)
                .selectAs(Course::getId, ScoreVo::getCourseId)
                .selectAs(Course::getName, ScoreVo::getCourseName)
                .selectAs(Score::getMark, ScoreVo::getMark)
                .innerJoin(User.class, User::getId, Score::getStudentId)
                .innerJoin(Course.class, Course::getId, Score::getCourseId)
                .eq(scoreVo.getStudentId() != null, User::getId, scoreVo.getStudentId())
                .eq(scoreVo.getCourseId() != null, Course::getId, scoreVo.getCourseId())
                .ge(scoreVo.getMark() != null, Score::getMark, lower)
                .le(scoreVo.getMark() != null, Score::getMark, upper);
        IPage<ScoreVo> scoreVoIPage = scoreMapper.selectJoinPage(new Page<ScoreVo>(page, size), ScoreVo.class, wrapper);
        if (scoreVoIPage != null && scoreVoIPage.getRecords().size() > 0)
            return Result.ok().data("scoreList", scoreVoIPage);
        return Result.ok().data("msg", "暂无数据").setCode(404);
    }
}
